import { AxiosError } from "axios";
import TokenManager from "./tokenManager";
import { RequestConfig, Response, PathVariables } from "./types";
import { defaultToastHandler } from "./toastHandler";
import request from ".";
/**
 * 通用重试机制
 * @param error
 * @param config
 * @param retryCount
 * @param maxTryCount
 * @param shouldRetry 自定义哪些错误类型需要重试
 * @param refreshTokenCallback 自定义如何刷新 token
 * @returns
 */
const retryRequest = async <
  D extends object = any,
  Q extends object = any,
  U extends string = string,
  P = PathVariables<U>
>(
  error: AxiosError,
  config: RequestConfig<D, Q, U, P>,
  retryCount: number,
  maxTryCount: number,
  shouldRetry: (error: AxiosError) => boolean,
  refreshTokenCallback: () => Promise<string | null>
): Promise<Response<any> | null> => {
  if (shouldRetry(error) && retryCount < maxTryCount) {
    const newToken = await refreshTokenCallback();
    if (newToken) {
      retryCount++;
      return request({ ...config });
    }
  }
  return null;
};
// 重试机制：401-刷新 token 后重新发送请求
export const retryWithRefreshToken = async <
  D extends object = any,
  Q extends object = any,
  U extends string = string,
  P = PathVariables<U>
>(
  error: AxiosError,
  config: RequestConfig<D, Q, U, P>,
  retryCount: number,
  maxTryCount: number
): Promise<Response<any> | null> => {
  return retryRequest(
    error,
    config,
    retryCount,
    maxTryCount,
    (err) => err.response?.status === 401, // 只对 401 错误进行重试
    TokenManager.refreshAccessToken
  );
};

// 统一处理请求错误和重试机制
export const handleRequestError = async <
  D extends object = any,
  Q extends object = any,
  U extends string = string,
  P = PathVariables<U>
>(
  error: AxiosError,
  config: RequestConfig<D, Q, U, P>,
  retryCount = 0,
  maxTryCount = 3
): Promise<Response<any>> => {
  const errMessage =
    (error.response?.data as Response<any>)?.errorMessage || "请求失败";
  if (!config.silentError) {
    defaultToastHandler.showToast(errMessage);
  }

  // 重试机制：对于 401 错误，尝试刷新 token 后重新发送请求
  // 默认处理401错误
  const retryResponse = await retryWithRefreshToken(
    error,
    config,
    retryCount,
    maxTryCount
  );
  if (retryResponse) return retryResponse;

  // 重试机制：对于其他错误，尝试重新发送请求

  return {
    success: false,
    errorCode: error.response?.status || 500,
    errorMessage: errMessage,
  };
};
